<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/5/19
 * Time: 10:08
 */

namespace app\admin\controller;
use think\Exception;

/**
 * Class GeneralController          |-此控制器是生成前台模板的控制器
 * @package app\admin\controller    |-需要与后台数据库参与
 */
class GeneralController extends CommonController
{
    private $files              =   '';
    private $columns            =   '';
    private $form_columns       =   '';
    private $init_tpl           =   ['add'=>'add.tpl','edit'=>'edit.tpl','index'=>'index.tpl'];
    private $init_vue           =   ['add'=>'add.vue','edit'=>'edit.vue','index'=>'index.vue'];
    private $restFullApi        =   [
        'index'=>'index',
        'create'=>'%s/create',
        'save'=>'%s',
        'read'=>'%s/:id',
        'edit'=>'%s/:id/edit',
        'update'=>'%s/:id',
        'delete'=>'%s/:id'
    ];
    private $edit_from          =   [];
    private $index_table        =   [];
    private $error_info         =   '';
    private $error_or_success   =   true;
    private $general_vue_ed     =   [];
    private $table_comment      =   '';
    private $sql                =   "SELECT COLUMN_NAME,column_comment FROM INFORMATION_SCHEMA.Columns WHERE table_name='%s' AND table_schema='%s'";
    private $tables_sql         =   "SELECT table_comment FROM INFORMATION_SCHEMA.tables  WHERE table_schema = '%s' AND table_name ='%s'";
    private $full_tables_sql    =   "SHOW FULL FIELDS from %s";
    private $general_fields     =   [];
    private $full_column_field  =   [];
    private $init_type          =   [
        'varchar'=>'text','password','time'=>'datetime','email','int'=>'number',
        'tinyint'=>'number',
        'file','radio','checkbox','image','submit','reset',
        'date','month','week','time','datatime-local','range',
        'url','search','color','tel'
    ];
    private $tableName          =   '';
    private $init_uri           =   '/api/admin/';
    /**
     * @author              |-开发人lqc
     * @dev_time            |-开发时间2017年5月19日10:27:32
     * @mod_time            |-修改时间（待修改）
     * @use                 |-通过配置自动生成前端后台需要的模板
     * @param $font_path    |-前端的路径
     * @param $general_path |-前端的需要写的路径
     * @param $dir_name     |-前端需要生成的文件加的名称
     * @param $model_name   |-对应的数据表名称
     * //SELECT COLUMN_NAME,column_comment FROM INFORMATION_SCHEMA.Columns WHERE table_name='dhf_user' AND table_schema='yongqiang'
     * //SHOW FULL FIELDS FROM dhf_user
     */
    private function general_tpl_handler($tables_name){
        $data_base                  =   config('database');
        $tableName                  =   trim($tables_name);
        if(array_key_exists('database',$data_base)===false){return false;}
        $prefix                     =   array_key_exists('prefix',$data_base)===false || empty($data_base['prefix'])?'':$data_base['prefix'];
        $this->tableName            =   $tableName;
        $tableName                  =   $prefix.$tableName;
        $tableNames                 =   db()->query('SHOW TABLES');
        $tableNames                 =   array_column($tableNames,'Tables_in_'.$data_base['database']);
        $data_base                  =   $data_base['database'];
        if(!in_array($tableName,$tableNames)){return false;}
        $sql                        =   vsprintf($this->sql,[$tableName,$data_base]);
        $table_comment_sql          =   vsprintf($this->tables_sql,[$data_base,$tableName]);
        $full_field_sql             =   vsprintf($this->full_tables_sql,[$tableName]);
        $this->columns              =   db()->query($sql);
        $this->table_comment        =   db()->query($table_comment_sql);
        $this->full_column_field    =   db()->query($full_field_sql);
        $this->table_comment        =   implode('',array_column($this->table_comment,'table_comment'));
        return true;
    }


    public function general_tpl_vue(){
        $controller             =   strtolower(input('module'));
        $data                   =   input();unset($data['module']);
        $this->_check_general($controller);
        $this->general_fields   =   $data;
        $result=$this->general_tpl_handler($controller);
        if(true===$result){
            $result             =
                $this->_check_tpl()
                    ->_handler_full()
                    ->_merge()
                    ->_general_add()
                    ->_general_edit()
                    ->_general_list()
                    ->_write_column();
            if(true===$result){return json(['status'=>1000,'data'=>'','info'=>'小惠已为您处理成功!'],200);}
            return json(['status'=>10001,'data'=>'','info'=>'小惠找不到你所要处理的控制器！'],204);
        }
        return json(['status'=>10001,'data'=>'','info'=>'小惠找不到你所要处理的控制器！'],204);
    }

    private function _handler_full(){
       $new_full            =   $new_full_field=[];
       array_map(function($element)use(&$new_full,&$new_full_field){
           $new_full['name']=$element['Field'];
           $new_full['type']=substr($element['Type'],0,strpos($element['Type'],chr(40)));
           $new_full_field[]=$new_full;
       },$this->full_column_field);
       $this->full_column_field=$new_full_field;
       return $this;
    }
    /**
     * @return $this|bool
     */
    private function _check_tpl(){
        $tpl_path                   =   THINK_PATH.'tpl'.DS;
        $fileIte                    =   new \FilesystemIterator($tpl_path);
        $files                      =   [];
        $fileIte->rewind();
        if($fileIte->isReadable()===false){$this->error_or_success=false;};
        if(true===$this->error_or_success):
            foreach($fileIte as $key=>$file):
                if(true===$file->isFile() && true===$file->isReadable() && $file->getExtension()==='tpl'):
                    $fileName            =   $file->getFilename();
                    if(in_array($fileName,$this->init_tpl))$files[]     =   $fileName;
                endif;
            endforeach;
            $this->files                =$files;
            if(sizeof($files)<3){$this->error_or_success=false;}
        endif;
        return $this;
    }

    /**
     * @param $controller
     * @return bool
     */
    private function _check_general($controller){
            $vue_template_path          =   config('vue_template_path');
            // 先判断当前的文件是否是文件夹 并且是否可写
            if(!is_dir($vue_template_path.$controller)){
                if(false===is_writable($vue_template_path)){$this->error_info='模板创建失败！模板目录您没有写权限'; return false;}
                @mkdir($vue_template_path.$controller,755);
            }
            if(is_dir($vue_template_path.$controller)){
                $fileIterator           =   new \FilesystemIterator($vue_template_path.$controller);
                $fileIterator->rewind();$fileNames=[];
                foreach($fileIterator as $key=>$fileItem){
                    $filename               =   $fileItem->getFilename();
                    if(in_array($filename,$this->init_vue)){$fileNames[]=$filename;}
                }
                // 已生成的模板
                $this->general_vue_ed       =   $fileNames;
                // 需要生成的模板
                $this->init_vue             =   array_diff($this->init_vue,$fileNames);
            }
    }



    private function _merge(){
        if(!empty($this->general_fields)){
            $columns                =   $this->columns;
            $inside_column          =   array_column($columns,'COLUMN_NAME');
            $full_column            =   array_combine(array_column($this->full_column_field,'name'),
                array_column($this->full_column_field,'type'));
            $that=$this;
            foreach($this->general_fields as $key=>$value){
                if(empty($value)){continue;}$fields_column              =   [];
                array_map(function($element)use($columns,&$fields_column,$inside_column,$full_column,$that){
                    $k_inside       =   array_search($element,$inside_column);
                    if(false!==$k_inside){
                        $new_columns                  =     $that->_handler_comment($columns[$k_inside],$full_column);
                        $fields_column[$k_inside]     =     $new_columns;
                    }
                },$value);
                ksort($fields_column);
                if(!empty($fields_column)&&'addField'==$key)$this->form_columns =   $fields_column;
                if(!empty($fields_column)&&'indexField'==$key)$this->index_table=   $fields_column;
                if(!empty($fields_column)&&'editField'==$key)$this->edit_from   =   $fields_column;
            }
        }else{$this->error_or_success=false;}
        return $this;
    }

    private function _handler_comment($column,$full_column){
        $new_column                             =[];
        if(false===strpos($column['column_comment'],chr(124))){
            if(array_key_exists($column['COLUMN_NAME'],$full_column)){
                if(false!==strpos($column['COLUMN_NAME'],'time')){
                    $type                       =      'time';
                }else{
                    $type                       =       $full_column[$column['COLUMN_NAME']];
                }
                $new_column['COLUMN_NAME']      =       $column['COLUMN_NAME'];
                $new_column['column_comment']   =       $column['column_comment'].chr(124).$this->init_type[$type];
                return $new_column;
            }
        }else{return $column;}
    }
    /**
     * @return $this
     */
    private function _general_add(){
        // 判断是否生成
        if(!isset($this->init_vue['add']) ||  true===in_array($this->init_vue['add'],$this->general_vue_ed)){return $this;}
        $columns                    =   $this->form_columns;
        if(is_array($columns) && !empty($columns)):
            $column                 =   [];
            foreach($columns as $key=>$value):
                $cut                =   $this->_cut_column($value);
                if(!empty($cut)){$column[$key]=$cut;}
            endforeach;
        $this->form_columns         =   $column;
        endif;
        if(!empty($this->form_columns)){
          $add_tpl                  =   $this->files[array_search($this->init_tpl['add'],$this->files)];
          $this->init_uri           =   $this->init_uri.$this->tableName.'/save';
          ob_start();
          require                       THINK_PATH.'tpl'.DS.$add_tpl;
          $content                  =   ob_get_contents();
          file_put_contents(config('vue_template_path').$this->tableName.DS.$this->init_vue['add'],$content);
          ob_clean();
        }
        return $this;
    }
    /**
     * @return $this
     */
    private function _general_edit(){
        if(!isset($this->init_vue['edit']) ||  true==in_array($this->init_vue['edit'],$this->general_vue_ed)){return $this;}
        $columns                      =   $this->edit_from;
        if(is_array($columns) && !empty($columns)):
            $column                   =   [];
            foreach($columns as $key=>$value):
                $cut                  =   $this->_cut_column($value);
                if(!empty($cut)){$column[$key]=$cut;}
            endforeach;
            $this->edit_from          =   $column;
        endif;
        if(!empty($this->edit_from)){
            $this->init_uri           =   '/api/admin/';
            $edit_tpl                 =   $this->files[array_search($this->init_tpl['edit'],$this->files)];
            $update_uri               =   $this->init_uri.$this->tableName.'/update/id';
            $this->init_uri           =   $this->init_uri.$this->tableName.'/read';
            ob_start();
            require                       THINK_PATH.'tpl'.DS.$edit_tpl;
            $content                  =   ob_get_contents();
            file_put_contents(config('vue_template_path').$this->tableName.DS.$this->init_vue['edit'],$content);
            ob_clean();
        }
       return $this;
    }



    /**
     * 生成列表页面
     */
    private function _general_list(){
        if(!isset($this->init_vue['index'])  ||  true===in_array($this->init_vue['index'],$this->general_vue_ed)){return $this;}
        $columns                    =   $this->index_table;
        if(is_array($columns) && !empty($columns)):
            $column                 =   [];
            foreach($columns as $key=>$value):
                $cut                =   $this->_cut_column($value);
                if(!empty($cut)){$column[$key]=$cut;}
            endforeach;
            $this->index_table         =   $column;
        endif;
        if(!empty($this->index_table)){
            $this->init_uri             =   '/api/admin/';
            $index_tpl                  =   $this->files[array_search($this->init_tpl['index'],$this->files)];
            $index_uri                  =   $this->init_uri.$this->tableName.'/index';
            ob_start();
            require                     THINK_PATH.'tpl'.DS.$index_tpl;
            $content                    =   ob_get_contents();
            file_put_contents(config('vue_template_path').$this->tableName.DS.$this->init_vue['index'],$content);
            ob_clean();
        }
        return $this;
    }

    private function _write_column(){
        $config_columns_path        =   CONF_PATH.$this->request->module().DS.'extra'.DS.'column.php';
        $columns_config             =   require $config_columns_path;
        if(!empty($this->columns)){
            $tables_columns         =   array_combine(array_column($this->columns,'COLUMN_NAME'),array_column($this->columns,'COLUMN_NAME'));
            $index_columns          =   array_combine(array_column($this->index_table,'COLUMN_NAME'),array_column($this->index_table,'COLUMN_NAME'));
            $add_columns            =   array_combine(array_column($this->form_columns,'COLUMN_NAME'),array_column($this->form_columns,'COLUMN_NAME'));
            $edit_columns           =   array_combine(array_column($this->edit_from,'COLUMN_NAME'),array_column($this->edit_from,'COLUMN_NAME'));
            $edit_columns['id']     =   'id';
            $columns_page['all']    =   $tables_columns;
            $columns_page['index']  =   $index_columns;
            $columns_page['save']    =   $add_columns;
            $columns_page['edit']   =   $edit_columns;
            $columns_config[$this->tableName]=$columns_page;
            ob_start();
            $column_path            =   'column.tpl';
            require                 THINK_PATH.'tpl'.DS.$column_path;
            $header                 ="<?php  \r\n return ";
            $content                = ob_get_contents().";";
            if(strpos($content,"\r\n")!==false){
                $content                =str_replace("\r\n",'',$content);
            }
            $content                    =$header.$content;
            if(strpos($content,chr(40))!==false){
                $content                =str_replace(chr(40),chr(91),$content);
            }
            if(strpos($content,chr(41))!==false){
                $content                    =str_replace(chr(41),chr(93),$content);
            }
            if(strpos($content,'array')!==false){
                $content                =str_replace('array','',$content);
            }
            file_put_contents($config_columns_path,$content);
            ob_clean();
        }
        return true;
    }
    /**
     * @param $value
     * @return array
     */
    private function _cut_column($value){

        $value                          =   array_values($value);
        $cut_column_group               =   [];
        $name                           =   $value[count($value)-count($value) & count($value)];
        $title_type                     =   $value[count($value)-count($value) | count($value)-1];
        $cut_column_group['name']       =   $name;
        // 124  ->|  40->(   41->)  45 ->-  44->,
        if(false==!strpos($title_type,chr(124))) {
            $group = explode(chr(124), $title_type);
            $title = $group[count($group) - count($group) & count($group)];
            $cut_column_group['title'] =    $title;
            $type = $group[count($group) - count($group) | count($group) - 1];
            if (false === strpos($type, chr(40))) {
                $cut_column_group['type'] = $type;
            } else {
                $cut_column_group['type']['real_type'] = substr($type, 0, strpos($type, chr(40)));
                $other_type = substr($type, strpos($type, chr(40)));
                $other_type = explode(chr(44), trim(trim($other_type, chr(40)), chr(41)));
                $new_other = [];
                foreach ($other_type as $key => $item):
                    $i_item = explode(chr(45), $item);
                    $new_other[$key]['title'] = $i_item[count($item - 1)];
                    $new_other[$key]['value'] = $i_item[count($item) - count($item)];
                endforeach;
                $cut_column_group['type']['other_value'] = $new_other;
            }
        }
        return $cut_column_group;
    }

    /**
     * @return $this  |-生成全段需要的表单头
     */
    public function column_config(){
        $controller                             =   trim(strtolower(input('controller')));
        $result                                 =   $this->general_tpl_handler($controller);
        $this->_check_general($controller);
        if(true===$result){
            if(!empty($this->columns)){
                $return_data                    =   [];
                foreach($this->columns as $key=>$value) {
                    $title                      =   $value['column_comment'];
                    if(strpos($value['column_comment'],chr(124))!==false){
                        $title                  =   substr($value['column_comment'],0,strpos($value['column_comment'],chr(124)));
                    }$return_data[$key]['name'] =   $value['COLUMN_NAME'];$return_data[$key]['title'] =$title;}
            }
            $tip                                ='';
            if(!empty($this->general_vue_ed)){$tip= implode(',',$this->general_vue_ed)."页面已存在，如生成会覆盖原来页面请慎重！";}
            return json(['status'=>1000,'data'=>$return_data,'info'=>'小惠已为您处理成功!'.$tip],200);}
        return json(['status'=>10001,'data'=>'','info'=>'小惠找不到你所要处理的控制器！'],204);
    }
}